import os
import pygetwindow as gw
import pyautogui
import serial
import time
import pyperclip

#需要按照实际情况设置
串口设备 = "COM13"
镜像文件路径 = "C:\\Users\\Admin\\Desktop\\SDK新唐NUC980\\NuWriteV1.16_AutoTools\\sys_image"
下载工具路径 = "NuWriter.exe"

uboot_splice = "u-boot-spl.bin"
uboot = "u-boot.bin"
env_local = "env_local.txt"
env_net = "env_net.txt"
kernel = "980uimage"
rootfs = "rootfs_yaffs2.img"

uboot_splice_offset = "200"
uboot_offset = "100000"
env_offset = "80000"
kernel_offset = "200000"
rootfs_offset = "1600000"


def 使用粘贴板输入通用文本(text):
    pyperclip.copy(text)
    pyautogui.hotkey('ctrl', 'v')

def 文件浏览器_输入文件路径(path):
    pyautogui.hotkey('alt', 'd')
    使用粘贴板输入通用文本(path)
    pyautogui.press('enter')

def 文件浏览器_输入文件名(path):
    pyautogui.hotkey('alt', 'n')
    使用粘贴板输入通用文本(path)
    pyautogui.press('enter')

def 选择目标文件(path, fileName):
    # 找到"打开文件"按钮的位置，使用图片 img\openFileImg.jpg
    打开文件_控件_图像 = pyautogui.locateOnScreen('img\openFileImg.jpg', confidence=0.5)
    打开文件_控件_中心位置 = pyautogui.center(打开文件_控件_图像)
    pyautogui.click(打开文件_控件_中心位置)
    # 等待文件浏览器成为活动窗口,检测img\choose_burning_file.jpg
    while(1):
        try:
            选择文件_控件_图像 = pyautogui.locateOnScreen('img\choose_burning_file.jpg', confidence=0.5)
        except:
            选择文件_控件_图像 = None
        if(选择文件_控件_图像 != None):
            break

    文件浏览器_输入文件路径(path)
    文件浏览器_输入文件名(fileName)

def 获取程序窗口位置(nuWriter):
    nuWriter.activate()
    left = nuWriter.left
    top = nuWriter.top
    width = nuWriter.width
    height = nuWriter.height
    return left, top, width, height

def 点击_Data_单选框(nuWriter):
    #点击相对位置(405,161)
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 405, top + 187)

def 点击_Env_单选框(nuWriter):
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 461, top + 187)

def 点击_Loader_单选框(nuWriter):
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 551, top + 187)

def 点击_ImageStartOffset_输入框(nuWriter, offset):
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 483, top + 252)
    #全选
    pyautogui.hotkey('ctrl', 'a')
    #删除
    pyautogui.press('delete')
    #输入
    使用粘贴板输入通用文本(offset)

def 点击_连接or断开连接_按钮(nuWriter):
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 656, top + 95)

def 点击_ImageSExecuteAddress_输入框(nuWriter, offset):
    nuWriter.activate()
    left, top, width, height = 获取程序窗口位置(nuWriter)
    pyautogui.click(left + 516, top + 221)
    #全选
    pyautogui.hotkey('ctrl', 'a')
    #删除
    pyautogui.press('delete')
    #输入
    使用粘贴板输入通用文本(offset)

def 等待出现确认弹窗():
    while(1):
        try:
            确认_控件_图像 = pyautogui.locateOnScreen('img\Successfully.jpg', confidence=0.5)
        except:
            确认_控件_图像 = None
        if(确认_控件_图像 != None):
            break

        #检查是否出现错误弹窗 img\ACK_ERROR.jpg
        try:
            错误_控件_图像 = pyautogui.locateOnScreen('img\ACK_ERROR.jpg', confidence=0.5)
        except:
            错误_控件_图像 = None
        if(错误_控件_图像 != None):
            pyautogui.alert(text='严重错误，无法恢复，连接已丢失！', title='连接丢失', button='确认并终止程序')
            exit()

def 重新连接设备(nuWriter):
    #可以识别 img\Connect_ERROR.jpg 或者 img\Connect_OK.jpg 判断连接状态
    #尝试识别有没有Connect_OK(只需要识别一次)，有的话先调用 断开连接按钮
    #重新发送流控信号，然后点击连接按钮，直到识别出Connect_OK
    while(1):
        #发送流控信号
        串口.setRTS(False)
        串口.setDTR(False)
        time.sleep(0.5)
        串口.setRTS(True)
        #点击连接按钮
        点击_连接or断开连接_按钮(nuWriter)
        #识别连接状态7
        time.sleep(5)
        try:
            连接OK_控件_图像 = pyautogui.locateOnScreen('img\Connect_OK.jpg', confidence=0.5)
        except:
            连接OK_控件_图像 = None
        if(连接OK_控件_图像 != None):
            break
        
    

if __name__ == '__main__':
    #选择启动模式 生产模式/网络启动模式
    运行模式 = pyautogui.confirm(text='请选择启动模式', title='启动模式', buttons=['生产模式', '网络启动模式'])
    #选择是否需要通过串口流控信号自动复位
    自动流控信号复位 = pyautogui.confirm(text='是否需要自动串口下载(如果硬件支持)', title='复位模式', buttons=['是', '否'])


    if (自动流控信号复位=='是'):
        #打开串口并设置流控信号 RTS=0 DTR=0
        串口 = serial.Serial(串口设备, 115200)
        # 等待500ms后设置 RTS=1，进入DFU模式
        串口.setRTS(False)
        串口.setDTR(False)
        time.sleep(0.5)
        串口.setRTS(True)

    #运行下载工具.exe，注意不得堵塞
    os.system("start " + 下载工具路径)

    #点击下载工具的"连接"按钮 img\continue.jpg 可以用try不停尝试
    while(1):
        try:
            nuWriter = gw.getWindowsWithTitle('Nuvoton NuWriter v1.16')[0]
            nuWriter.activate()
            连接_控件_图像 = pyautogui.locateOnScreen('img\continue.jpg', confidence=0.5)
            连接_控件_中心位置 = pyautogui.center(连接_控件_图像)
            pyautogui.click(连接_控件_中心位置)
        except:
            连接_控件_图像 = None
        if(连接_控件_图像 != None):
            break
        
    #等待下载软件打开，可以通过try识别 img\mainScreenLogo.jpg
    while(1):
        try:
            新唐_图标_图像 = pyautogui.locateOnScreen('img\mainScreenLogo.jpg', confidence=0.5)
        except:
            新唐_图标_图像 = None
        if(新唐_图标_图像 != None):
            break

    while(1):

        
        # 获取程序窗口
        nuWriter = gw.getWindowsWithTitle('Nuvoton NuWriter v1.16')[0]
        # 置于前台
        nuWriter.activate()
        time.sleep(0.5)


        #找到 img\Program.jpg
        编程_控件_图像 = pyautogui.locateOnScreen('img\Program.jpg', confidence=0.5)
        编程_控件_中心位置 = pyautogui.center(编程_控件_图像)


        if (运行模式 == '生产模式'):
            # 找到 img\Erase.jpg
            擦除_控件_图像 = pyautogui.locateOnScreen('img\Erase.jpg', confidence=0.5)
            擦除_控件_中心位置 = pyautogui.center(擦除_控件_图像)
            #点击擦除
            pyautogui.click(擦除_控件_中心位置)
            #回车
            pyautogui.press('enter')
            #等待擦除完成
            等待出现确认弹窗()

        #写入 uboot_splice
        选择目标文件(镜像文件路径, uboot_splice)
        点击_Loader_单选框(nuWriter)
        点击_ImageSExecuteAddress_输入框(nuWriter, uboot_splice_offset)
        pyautogui.click(编程_控件_中心位置)
        time.sleep(0.5)
        #回车确认
        pyautogui.press('enter')
        #等待烧录完成
        等待出现确认弹窗()
        pyautogui.press('enter')

        # #写入 uboot
        选择目标文件(镜像文件路径, uboot)
        点击_Data_单选框(nuWriter)
        点击_ImageStartOffset_输入框(nuWriter, uboot_offset)
        pyautogui.click(编程_控件_中心位置)
        time.sleep(0.5)
        #回车确认
        pyautogui.press('enter')
        #等待烧录完成
        等待出现确认弹窗()
        pyautogui.press('enter')

        #写入 kernel
        选择目标文件(镜像文件路径, kernel)
        点击_Data_单选框(nuWriter)
        点击_ImageStartOffset_输入框(nuWriter,  kernel_offset)
        pyautogui.click(编程_控件_中心位置)
        time.sleep(0.5)
        #回车确认
        pyautogui.press('enter')
        #等待烧录完成
        等待出现确认弹窗()
        pyautogui.press('enter')

        if (运行模式 == '生产模式'):
            env = env_local
        else:
            env = env_net

        #写入 env
        选择目标文件(镜像文件路径, env)
        点击_Env_单选框(nuWriter)
        点击_ImageStartOffset_输入框(nuWriter, env_offset)
        pyautogui.click(编程_控件_中心位置)
        time.sleep(0.5)
        #回车确认
        pyautogui.press('enter')
        #等待烧录完成
        等待出现确认弹窗()
        pyautogui.press('enter')

        if (运行模式 == '生产模式'):
            #写入 rootfs
            选择目标文件(镜像文件路径, rootfs)
            点击_Data_单选框(nuWriter)
            点击_ImageStartOffset_输入框(nuWriter, rootfs_offset)
            pyautogui.click(编程_控件_中心位置)
            time.sleep(0.5)
            #回车确认
            pyautogui.press('enter')
            #等待烧录完成
            等待出现确认弹窗()
            pyautogui.press('enter')



        #发起弹窗，让用户确认操作，则继续，否则退出
        用户选择 = pyautogui.confirm(text='烧录成功，是否继续操作', title='成功', buttons=['继续生产', '退出生产操作'])
        if(用户选择 == '继续生产'):
            if (自动流控信号复位=='是'):
                重新连接设备(nuWriter)
        else:
            break